﻿using Bouyei.Geo.Geometries;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Bouyei.Geo.GeoParsers.Wkb
{
    public class GeometryReader : BaseBytes
    {
        public GeoType GeometryType { get;private set; }

        public GeometryReader(byte[] buffer,int offset=0)
            :base(buffer,offset)
        {

        }

        public GeometryReader(byte[] buffer, int offset, ByteOrder byteOrder)
            : base(buffer,byteOrder,offset)
        {
 
        }

        public unsafe Geometry Reader()
        {
            Geometry geo = null;
            fixed (byte* ptr = &Buffer[Offset])
            {
                GeometryType = (GeoType)bitExt.ToInt32(ptr);
                byte* start = ptr + 4;

                switch (GeometryType)
                {
                    case GeoType.POINT:
                        {
                            var point = new WkbPoint(bitExt, start);
                            geo= new Geometry(point.Coord);
                        }break;
                    case GeoType.MULTIPOINT:
                        {
                            var multipoint = new WkbMultiPoint(bitExt, start);
                            geo = new Geometry(GeoType.MULTIPOINT, multipoint.GetCoordinates());
                        }break;
                    case GeoType.LINESTRING:
                        {
                            var linestring = new WkbLineString(bitExt, start);
                            geo = new Geometry(GeoType.LINESTRING, linestring.GetCoordinates());
                        }break;
                    case GeoType.MULTILINESTRING:
                        {
                            var multilinestring = new WkbMultiLineString(bitExt, start);
                            geo = new Geometry(GeoType.MULTILINESTRING, multilinestring.GetCoordinates());
                        }break;
                    case GeoType.POLYGON:
                        {
                            var polygon = new WkbPolygon(bitExt, start);
                            if (polygon.Count == 1) geo = new Geometry(GeoType.POLYGON, polygon[0].Coords);
                            else if (polygon.Count > 1) geo = new Geometry(polygon[0].Coords, polygon.GetInteriorRing()); 
                        }break;
                    case GeoType.MULTIPOLYGON:
                        {
                            var multiPolygon = new WkbMultiPolygon(bitExt, start);
                            List<GeoPolygon> polygons = new List<GeoPolygon>(multiPolygon.Count);

                            foreach (WkbPolygon polygon in multiPolygon)
                            {
                                if (polygon.Count == 1)
                                    polygons.Add(new GeoPolygon(polygon.GetOuterRing()));
                                else if (polygon.Count >= 2)
                                    polygons.Add(new GeoPolygon(polygon.GetOuterRing(), polygon.GetInteriorRing()));
                            }
                            geo = new Geometry(polygons.ToArray());
                        }break;
                    default:
                        throw new Exception("geometryType not supported" + GeometryType);
                }
            }
            return geo;
        }

    }
}
